(function() {
	module('Lock Tests');

	test('Setup OK', function() {
		ok(true);
	});

	test('test initial state', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();

		var expectedPositions = [ 1, 2, 1 ];

		deepEqual(view.blocksPositions, expectedPositions);
	});

	test('test move block 0', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(0, +1);

		var expectedPositions = [ 2, 3, 1 ];

		deepEqual(view.blocksPositions, expectedPositions);
	});

	test('test move block 1', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(1, -1);

		var expectedPositions = [ 0, 1, 1 ];

		deepEqual(view.blocksPositions, expectedPositions);
	});

	test('test not allowed move block 3', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(2, -1);

		var expectedPositions = [ 1, 2, 1 ];
		deepEqual(view.blocksPositions, expectedPositions);
	});

	test('test stale after 3 moves', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(0, -1);
		controller.onMove(1, +1);
		controller.onMove(2, +1);

		ok(view.onStaleCalled);
	});

	test('test cannot move after stale', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(0, -1);
		controller.onMove(1, +1);
		controller.onMove(2, +1);

		ok(view.onStaleCalled);

		var moved = controller.onMove(2, -1);
		ok(!moved);
	});

	test('test stale after solution', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(0, -1);
		controller.onMove(2, +1);
		controller.onMove(2, +1);

		// Move after winning position reached causes stale.
		var moved = controller.onMove(1, -1);
		ok(!moved);

		ok(view.onStaleCalled);
	});

	test('test a solution', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(0, -1);
		controller.onMove(2, +1);
		controller.onMove(2, +1);

		var expectedPositions = [ 0, 3, 3 ];
		deepEqual(view.blocksPositions, expectedPositions);

		var opened = controller.onOpenLock();
		ok(opened);
		ok(view.onSolvedCalled);
		ok(!view.onStaleCalled);
	});

	test('test not allowed causes no state change', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(0, -1);
		controller.onMove(2, +1);
		controller.onMove(2, +1);

		// Move not allowed, that cause no state change.
		controller.onMove(1, +1);
		controller.onOpenLock();

		ok(view.onSolvedCalled);
	});

	test('test reset', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(0, -1);
		controller.onMove(2, +1);

		controller.reset();

		deepEqual(view.resetPositions, [ 1, 2, 1 ]);
		deepEqual(view.buttonsState, [ true, true, true, true, false, true ]);
	});

	test('test initial button state', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();

		deepEqual(view.buttonsState, [ true, true, true, true, false, true ]);
	});

	test('test button state after move', function() {
		var view = new TestView();
		var controller = new LockController(view);

		controller.startup();
		controller.onMove(1, -1);

		deepEqual(view.buttonsState, [ false, true, false, true, false, true ]);
	});

	function TestView() {
		this.onSolvedCalled = false;
		this.onStaleCalled = false;
	}

	TestView.prototype.init = function(controller) {
	};

	TestView.prototype.update = function(blocksPositions) {
		this.blocksPositions = blocksPositions;
	};

	TestView.prototype.updateButtons = function(buttonsState) {
		this.buttonsState = buttonsState;
	};

	TestView.prototype.onSolved = function() {
		this.onSolvedCalled = true;
	};

	TestView.prototype.onStale = function() {
		this.onStaleCalled = true;
	};

	TestView.prototype.onReset = function(resetPositions) {
		this.resetPositions = resetPositions;
	};
}());